package com.pcg.posgasstation.view;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.NfcA;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.pcg.posgasstation.R;
import com.pcg.posgasstation.base.BaseActivity;
import com.pcg.posgasstation.model.Constant;
import com.pcg.posgasstation.model.network.ApiClient;
import com.pcg.posgasstation.model.network.entity.BaseEntity;
import com.pcg.posgasstation.utils.DialogHelper;
import com.pcg.posgasstation.utils.LogUtil;
import com.pcg.posgasstation.utils.ToastUtils;
import com.pcg.posgasstation.utils.Utils;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.qqtheme.framework.picker.DatePicker;
import cn.qqtheme.framework.util.ConvertUtils;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

public class AddMemberActivity extends BaseActivity {

    @BindView(R.id.layTvBack)
    ImageView mLayTvBack;
    @BindView(R.id.layBack)
    RelativeLayout mLayBack;
    @BindView(R.id.layTvTitle)
    TextView mLayTvTitle;
    @BindView(R.id.edtMemberName)
    EditText mEdtMemberName;
    @BindView(R.id.edtMemberPhone)
    EditText mEdtMemberPhone;
    @BindView(R.id.edtVerifyCode)
    EditText mEdtVerifyCode;
    @BindView(R.id.tvGetVerifyCode)
    TextView mTvGetVerifyCode;
    @BindView(R.id.edtPayPassword)
    EditText mEdtPayPassword;
    @BindView(R.id.tvNfcCardNum)
    TextView mTvNfcCardNum;
    @BindView(R.id.btnAddMember)
    Button mBtnAddMember;
    @BindView(R.id.viewActionBarDivider)
    View mViewActionBarDivider;
    @BindView(R.id.edtMemberIdCard)
    EditText mEdtMemberIdCard;
    @BindView(R.id.edtMemberCarNo)
    EditText mEdtMemberCarNo;
    @BindView(R.id.tvMemberSex)
    TextView mTvMemberSex;
    @BindView(R.id.tvMemberBirthday)
    TextView mTvMemberBirthday;

    private static final String TAG = AddMemberActivity.class.getSimpleName();

    // TEST
//    private String mNfcCardNum = "021000003";
    private String mNfcCardNum = "";

    // nfc begin
    private NfcAdapter mAdapter;
    private PendingIntent mPendingIntent;
    private NdefMessage mNdefPushMessage;

    private List<Tag> mTags = new ArrayList<Tag>();
    // nfc end

    // 2019.3.2 new params
    private int mSex = -1; // 会员性别（ 0：男；1：女；）
    private String mBirthday = ""; // 年月日 （2019-02-03）

    private String mPhoneNumber;

    public static void startActivity(Context context) {
        Intent intent = new Intent();
        intent.setClass(context, AddMemberActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_member);
        ButterKnife.bind(this);

        initViews();
        initNfc();
    }

    // nfc begin

    @Override
    protected void onResume() {
        super.onResume();
        if (mAdapter != null) {
            if (!mAdapter.isEnabled()) {
                showWirelessSettingsDialog();
            }
            mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
            mAdapter.enableForegroundNdefPush(this, mNdefPushMessage);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mAdapter != null) {
            mAdapter.disableForegroundDispatch(this);
            mAdapter.disableForegroundNdefPush(this);
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        setIntent(intent);
        resolveIntent(intent);
    }

    private void initNfc() {
        resolveIntent(getIntent());

        mAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mAdapter == null) {
            ToastUtils.showToast("没有NFC");
//            finish();
            return;
        }

        mPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        mNdefPushMessage = new NdefMessage(new NdefRecord[]{newTextRecord(
                "Message from NFC Reader :-)", Locale.ENGLISH, true)});
    }

    private void showWirelessSettingsDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.nfc_disabled);
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialogInterface, int i) {
                Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
                startActivity(intent);
            }
        });
        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialogInterface, int i) {
                finish();
            }
        });
        builder.create().show();
        return;
    }

    private NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) {
        byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));

        Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
        byte[] textBytes = text.getBytes(utfEncoding);

        int utfBit = encodeInUtf8 ? 0 : (1 << 7);
        char status = (char) (utfBit + langBytes.length);

        byte[] data = new byte[1 + langBytes.length + textBytes.length];
        data[0] = (byte) status;
        System.arraycopy(langBytes, 0, data, 1, langBytes.length);
        System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);

        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
    }

    private void resolveIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage[] msgs;
            if (rawMsgs != null) {
                msgs = new NdefMessage[rawMsgs.length];
                for (int i = 0; i < rawMsgs.length; i++) {
                    msgs[i] = (NdefMessage) rawMsgs[i];
                }
            } else {
                // Unknown tag type
                byte[] empty = new byte[0];
                byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
                Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                byte[] payload = dumpTagData(tag).getBytes();
                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, id, payload);
                NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
                msgs = new NdefMessage[]{msg};
                mTags.add(tag);
            }
            // Setup the views
            buildTagViews(msgs);
        }
    }

    private void buildTagViews(NdefMessage[] msgs) {
        if (msgs == null || msgs.length == 0) {
            return;
        }
        // Parse the first message in the list
        // Build views for all of the sub records
        NdefRecord[] ndefRecords = msgs[0].getRecords();
        if (ndefRecords != null && ndefRecords.length > 0) {
            byte[] playLoadByte = ndefRecords[0].getPayload();
            String textCardNum = new String(playLoadByte);
            LogUtil.e(TAG, "nfc record card number = " + textCardNum);

            mNfcCardNum = textCardNum;
            mTvNfcCardNum.setText(mNfcCardNum);
        }

//        List<ParsedNdefRecord> records = NdefMessageParser.parse(msgs[0]);
//        final int size = records.size();
//        for (int i = 0; i < size; i++) {
//            ParsedNdefRecord record = records.get(i);
////            record.getView()
//            LogUtil.e(TAG,"nfc record");
//        }
    }

    private String dumpTagData(Tag tag) {
        StringBuilder sb = new StringBuilder();
        byte[] id = tag.getId();
        sb.append(toDec(id));

//        sb.append("ID (hex): ").append(toHex(id)).append('\n');
//        sb.append("ID (reversed hex): ").append(toReversedHex(id)).append('\n');
//        sb.append("ID (dec): ").append(toDec(id)).append('\n');
//        sb.append("ID (reversed dec): ").append(toReversedDec(id)).append('\n');

//        String prefix = "android.nfc.tech.";
//        sb.append("Technologies: ");
//        for (String tech : tag.getTechList()) {
//            sb.append(tech.substring(prefix.length()));
//            sb.append(", ");
//        }
//        sb.delete(sb.length() - 2, sb.length());
//        for (String tech : tag.getTechList()) {
//            if (tech.equals(MifareClassic.class.getName())) {
//                sb.append('\n');
//                String type = "Unknown";
//                try {
//                    MifareClassic mifareTag;
//                    try {
//                        mifareTag = MifareClassic.get(tag);
//                    } catch (Exception e) {
//                        // Fix for Sony Xperia Z3/Z5 phones
//                        tag = cleanupTag(tag);
//                        mifareTag = MifareClassic.get(tag);
//                    }
//                    switch (mifareTag.getType()) {
//                        case MifareClassic.TYPE_CLASSIC:
//                            type = "Classic";
//                            break;
//                        case MifareClassic.TYPE_PLUS:
//                            type = "Plus";
//                            break;
//                        case MifareClassic.TYPE_PRO:
//                            type = "Pro";
//                            break;
//                    }
//                    sb.append("Mifare Classic type: ");
//                    sb.append(type);
//                    sb.append('\n');
//
//                    sb.append("Mifare size: ");
//                    sb.append(mifareTag.getSize() + " bytes");
//                    sb.append('\n');
//
//                    sb.append("Mifare sectors: ");
//                    sb.append(mifareTag.getSectorCount());
//                    sb.append('\n');
//
//                    sb.append("Mifare blocks: ");
//                    sb.append(mifareTag.getBlockCount());
//                } catch (Exception e) {
//                    sb.append("Mifare classic error: " + e.getMessage());
//                }
//            }
//
//            if (tech.equals(MifareUltralight.class.getName())) {
//                sb.append('\n');
//                MifareUltralight mifareUlTag = MifareUltralight.get(tag);
//                String type = "Unknown";
//                switch (mifareUlTag.getType()) {
//                    case MifareUltralight.TYPE_ULTRALIGHT:
//                        type = "Ultralight";
//                        break;
//                    case MifareUltralight.TYPE_ULTRALIGHT_C:
//                        type = "Ultralight C";
//                        break;
//                }
//                sb.append("Mifare Ultralight type: ");
//                sb.append(type);
//            }
//        }

        return sb.toString();
    }

    private Tag cleanupTag(Tag oTag) {
        if (oTag == null)
            return null;

        String[] sTechList = oTag.getTechList();

        Parcel oParcel = Parcel.obtain();
        oTag.writeToParcel(oParcel, 0);
        oParcel.setDataPosition(0);

        int len = oParcel.readInt();
        byte[] id = null;
        if (len >= 0) {
            id = new byte[len];
            oParcel.readByteArray(id);
        }
        int[] oTechList = new int[oParcel.readInt()];
        oParcel.readIntArray(oTechList);
        Bundle[] oTechExtras = oParcel.createTypedArray(Bundle.CREATOR);
        int serviceHandle = oParcel.readInt();
        int isMock = oParcel.readInt();
        IBinder tagService;
        if (isMock == 0) {
            tagService = oParcel.readStrongBinder();
        } else {
            tagService = null;
        }
        oParcel.recycle();

        int nfca_idx = -1;
        int mc_idx = -1;
        short oSak = 0;
        short nSak = 0;

        for (int idx = 0; idx < sTechList.length; idx++) {
            if (sTechList[idx].equals(NfcA.class.getName())) {
                if (nfca_idx == -1) {
                    nfca_idx = idx;
                    if (oTechExtras[idx] != null && oTechExtras[idx].containsKey("sak")) {
                        oSak = oTechExtras[idx].getShort("sak");
                        nSak = oSak;
                    }
                } else {
                    if (oTechExtras[idx] != null && oTechExtras[idx].containsKey("sak")) {
                        nSak = (short) (nSak | oTechExtras[idx].getShort("sak"));
                    }
                }
            } else if (sTechList[idx].equals(MifareClassic.class.getName())) {
                mc_idx = idx;
            }
        }

        boolean modified = false;

        if (oSak != nSak) {
            oTechExtras[nfca_idx].putShort("sak", nSak);
            modified = true;
        }

        if (nfca_idx != -1 && mc_idx != -1 && oTechExtras[mc_idx] == null) {
            oTechExtras[mc_idx] = oTechExtras[nfca_idx];
            modified = true;
        }

        if (!modified) {
            return oTag;
        }

        Parcel nParcel = Parcel.obtain();
        nParcel.writeInt(id.length);
        nParcel.writeByteArray(id);
        nParcel.writeInt(oTechList.length);
        nParcel.writeIntArray(oTechList);
        nParcel.writeTypedArray(oTechExtras, 0);
        nParcel.writeInt(serviceHandle);
        nParcel.writeInt(isMock);
        if (isMock == 0) {
            nParcel.writeStrongBinder(tagService);
        }
        nParcel.setDataPosition(0);

        Tag nTag = Tag.CREATOR.createFromParcel(nParcel);

        nParcel.recycle();

        return nTag;
    }

    private String toHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = bytes.length - 1; i >= 0; --i) {
            int b = bytes[i] & 0xff;
            if (b < 0x10)
                sb.append('0');
            sb.append(Integer.toHexString(b));
            if (i > 0) {
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    private String toReversedHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; ++i) {
            if (i > 0) {
                sb.append(" ");
            }
            int b = bytes[i] & 0xff;
            if (b < 0x10)
                sb.append('0');
            sb.append(Integer.toHexString(b));
        }
        return sb.toString();
    }

    private long toDec(byte[] bytes) {
        long result = 0;
        long factor = 1;
        for (int i = 0; i < bytes.length; ++i) {
            long value = bytes[i] & 0xffl;
            result += value * factor;
            factor *= 256l;
        }
        return result;
    }

    private long toReversedDec(byte[] bytes) {
        long result = 0;
        long factor = 1;
        for (int i = bytes.length - 1; i >= 0; --i) {
            long value = bytes[i] & 0xffl;
            result += value * factor;
            factor *= 256l;
        }
        return result;
    }

    // nfc end

    private void initViews() {
        mProgressDialog = new ProgressDialog(this);
        mTvNfcCardNum.setText(mNfcCardNum);
    }

    @OnClick(R.id.tvGetVerifyCode)
    void getVerifyCodeClick() {
        String phone = mEdtMemberPhone.getText().toString();
        if (TextUtils.isEmpty(phone)) {
            ToastUtils.showToast("请输入会员手机");
            return;
        }
        mPhoneNumber = phone;
        getPhoneCaptchaCode(phone);
    }

    @OnClick(R.id.tvMemberSex)
    void memberSexClick() {
        DialogHelper.getInstance().showGenderDialog(mContext, mSex, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mSex = Constant.Gender.GENDER_BOY;
                mTvMemberSex.setText(getString(R.string.boy));
            }
        }, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mSex = Constant.Gender.GENDER_GIRL;
                mTvMemberSex.setText(getString(R.string.girl));
            }
        });
    }

    @OnClick(R.id.tvMemberBirthday)
    void memberBirthdayClick() {
        final DatePicker picker = new DatePicker(this);
        picker.setCanceledOnTouchOutside(true);
        picker.setUseWeight(true);
        picker.setTopPadding(ConvertUtils.toPx(this, 10));
        picker.setRangeEnd(2050, 12, 30);
        picker.setRangeStart(1900, 1, 1);
        picker.setSelectedItem(1980, 5, 1);
        picker.setResetWhileWheel(false);
        picker.setOnDatePickListener(new DatePicker.OnYearMonthDayPickListener() {
            @Override
            public void onDatePicked(String year, String month, String day) {
                mBirthday = (year + "-" + month + "-" + day);
                mTvMemberBirthday.setText(mBirthday);
            }
        });
        picker.setOnWheelListener(new DatePicker.OnWheelListener() {
            @Override
            public void onYearWheeled(int index, String year) {
                picker.setTitleText(year + "-" + picker.getSelectedMonth() + "-" + picker.getSelectedDay());
            }

            @Override
            public void onMonthWheeled(int index, String month) {
                picker.setTitleText(picker.getSelectedYear() + "-" + month + "-" + picker.getSelectedDay());
            }

            @Override
            public void onDayWheeled(int index, String day) {
                picker.setTitleText(picker.getSelectedYear() + "-" + picker.getSelectedMonth() + "-" + day);
            }
        });
        picker.show();
    }

    @OnClick(R.id.layBack)
    void backClick() {
        finish();
    }

    @OnClick(R.id.btnAddMember)
    void addMemberClick() {
        String name = mEdtMemberName.getText().toString();
        String phone = mEdtMemberPhone.getText().toString();
        String verifyCode = mEdtVerifyCode.getText().toString();
        String password = mEdtPayPassword.getText().toString();

        // new params
        String idCardNo = mEdtMemberIdCard.getText().toString();
        String carNo = mEdtMemberCarNo.getText().toString();
        // new params

        if (TextUtils.isEmpty(name)) {
            ToastUtils.showToast("请输入会员名称");
            return;
        }

        if (TextUtils.isEmpty(idCardNo)) {
            idCardNo = "";
        }

        if (TextUtils.isEmpty(carNo)) {
            ToastUtils.showToast("请输入车牌号");
            return;
        }

        if (mSex == -1) {
            ToastUtils.showToast("请选择会员性别");
            return;
        }

        if (TextUtils.isEmpty(phone)) {
            ToastUtils.showToast("请输入会员手机");
            return;
        }

        if (!TextUtils.equals(phone, mPhoneNumber)) {
            ToastUtils.showToast("验证码手机号与当前输入手机号不一致");
            return;
        }

        if (TextUtils.isEmpty(verifyCode)) {
            ToastUtils.showToast("请输入验证码");
            return;
        }

        if (TextUtils.isEmpty(password)) {
            ToastUtils.showToast("请输入支付密码");
            return;
        }

        if (TextUtils.isEmpty(mNfcCardNum)) {
            ToastUtils.showToast("请通过NFC识别会员卡号");
            return;
        }

        addMember(phone, name, mNfcCardNum, verifyCode, Utils.encryptionPassword(password), idCardNo, carNo,
                String.valueOf(mSex), mBirthday);
    }

    private void addMember(String phone, String name, String card, String verifyCode, String password,
                           String idCardNo, String carNo, String sex, String birthday) {
        mProgressDialog.show();
        ApiClient.getApiService().addMember(ApiClient.getToken(), phone, name, card, verifyCode,
                password, carNo, sex, idCardNo, birthday)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<BaseEntity<String>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        mDisposable.add(d);
                    }

                    @Override
                    public void onNext(BaseEntity<String> entity) {
                        mProgressDialog.hide();
                        if (entity != null) {
                            if (entity.isSuccess()) {
                                ToastUtils.showToast("添加成功");
                                finish();
                            } else {
                                ToastUtils.showToast(entity.getMsg());
                            }
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        mProgressDialog.hide();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void getPhoneCaptchaCode(String phoneNumber) {
        mProgressDialog.show();
        ApiClient.getApiService().getPhoneCaptchaCode(ApiClient.getToken(),phoneNumber)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<BaseEntity<String>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        mDisposable.add(d);
                    }

                    @Override
                    public void onNext(BaseEntity<String> entity) {
                        mProgressDialog.hide();
                        if (entity != null) {
                            if (entity.isSuccess()) {
                                mTvGetVerifyCode.setText("已发送");
                                ToastUtils.showToast("验证码已发送");
                            } else {
                                ToastUtils.showToast(entity.getMsg());
                            }
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        mProgressDialog.hide();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

}
